package com.foxchen.textinputapp.controller;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.foxchen.textinputapp.Constants;
import com.foxchen.textinputapp.common.ResponseBean;
import com.foxchen.textinputapp.dto.MaterialTableDTO;
import com.foxchen.textinputapp.enums.OutBoundStatusEnums;
import com.foxchen.textinputapp.exception.BaseException;
import com.foxchen.textinputapp.po.MaterialRecordPO;
import com.foxchen.textinputapp.service.MaterialService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

@CrossOrigin
@Controller
@RequestMapping("/material")
public class MaterialController {
    @Resource
    private MaterialService materialService;

    private static final Map<String, SFunction<MaterialRecordPO, Object>> ORDER_MAP = new HashMap<>();
    static {
        ORDER_MAP.put("name",MaterialRecordPO::getName);
        ORDER_MAP.put("model",MaterialRecordPO::getModel);
        ORDER_MAP.put("sn",MaterialRecordPO::getSn);
        ORDER_MAP.put("status",MaterialRecordPO::getStatus);
        ORDER_MAP.put("gmtCreate",MaterialRecordPO::getGmtCreate);
        ORDER_MAP.put("gmtModified",MaterialRecordPO::getGmtModified);
        ORDER_MAP.put("remark",MaterialRecordPO::getRemark);
    }
    @ResponseBody
    @PostMapping("list")
    public ResponseBean<Page<MaterialRecordPO>> listAll(@RequestBody MaterialTableDTO materialTableDTO){
        LambdaQueryWrapper<MaterialRecordPO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        if(StringUtils.isNotBlank(materialTableDTO.getName())){
            lambdaQueryWrapper.like(MaterialRecordPO::getName,materialTableDTO.getName());
        }
        if(StringUtils.isNotBlank(materialTableDTO.getSn())){
            lambdaQueryWrapper.like(MaterialRecordPO::getSn,materialTableDTO.getSn());
        }
        if(StringUtils.isNotBlank(materialTableDTO.getModel())){
            lambdaQueryWrapper.like(MaterialRecordPO::getModel,materialTableDTO.getModel());
        }
        if(StringUtils.isNotBlank(materialTableDTO.getStatus())){
            lambdaQueryWrapper.like(MaterialRecordPO::getStatus,materialTableDTO.getStatus());
        }
        if(StringUtils.isNotBlank(materialTableDTO.getRemark())){
            lambdaQueryWrapper.like(MaterialRecordPO::getRemark,materialTableDTO.getRemark());
        }
        if(StringUtils.isNotBlank(materialTableDTO.getCreateBegin()) && StringUtils.isNotBlank(materialTableDTO.getCreateEnd())){
            lambdaQueryWrapper.between(MaterialRecordPO::getGmtCreate,materialTableDTO.getCreateBegin(),materialTableDTO.getCreateEnd());
        }
        if(materialTableDTO.getOutBound() != null){
            lambdaQueryWrapper.eq(MaterialRecordPO::getOutBound,materialTableDTO.getOutBound());
        }
        // 排序
        lambdaQueryWrapper.orderBy(StringUtils.isNotBlank(materialTableDTO.getOrderBy()), "ASC".equals(materialTableDTO.getSort()), ORDER_MAP.getOrDefault(materialTableDTO.getOrderBy(),MaterialRecordPO::getName));

        Page<MaterialRecordPO> page;
        if(materialTableDTO.getPage() != null && materialTableDTO.getPageSize() != null){
            page = materialService.page(new Page<>(materialTableDTO.getPage(),materialTableDTO.getPageSize()),lambdaQueryWrapper);
        } else {
            List<MaterialRecordPO> data = materialService.list(lambdaQueryWrapper);
            page = new Page<>();
            page.setTotal(data.size());
            page.setRecords(data);
        }

        return ResponseBean.success(page);
    }

    @ResponseBody
    @PostMapping("add-or-edit")
    public ResponseBean<Boolean> addOrEdit(@RequestBody MaterialRecordPO materialRecordPO){
        if(StringUtils.isBlank(materialRecordPO.getName()) || StringUtils.isBlank(materialRecordPO.getModel()) || StringUtils.isBlank(materialRecordPO.getSn()) || StringUtils.isBlank(materialRecordPO.getStatus())){
            throw new BaseException("参数校验失败！");
        }
        String formatDateString = DateUtil.format(new Date(), Constants.TIME_FORMAT_BASE);
        if(materialRecordPO.getId() != null){
            materialRecordPO.setGmtModified(formatDateString);
        } else {
            materialRecordPO.setGmtCreate(formatDateString);
            materialRecordPO.setGmtModified(formatDateString);
        }

        return ResponseBean.success(materialService.saveOrUpdate(materialRecordPO));
    }

    @ResponseBody
    @GetMapping("match-name-model-by-sn/{sn}")
    public ResponseBean<Map<String,Set<String>>> matchNameModelBySn(@PathVariable String sn){
        if(StringUtils.isBlank(sn)){
            throw new BaseException("sn不合法!");
        }
        String sql = "AND LENGTH(sn) = %s";
        sql = String.format(sql, sn.length());
        List<MaterialRecordPO> dataList = materialService.list(new QueryWrapper<MaterialRecordPO>().last(sql));

        Set<String> nameList = new LinkedHashSet<>();
        Set<String> modelList = new LinkedHashSet<>();
        dataList.forEach(data -> {
                    nameList.add(data.getName());
                    modelList.add(data.getModel());
                });

        Map<String,Set<String>> returnMap = new HashMap<>();
        returnMap.put("nameList",nameList);
        returnMap.put("modelList",modelList);
        return ResponseBean.success(returnMap);
    }

    @ResponseBody
    @PostMapping("delete-by-ids")
    public ResponseBean<Boolean> deleteByIds(@RequestBody List<String> ids){
        if(CollectionUtils.isEmpty(ids)){
            return ResponseBean.success(Boolean.TRUE);
        }

        return ResponseBean.success(materialService.removeByIds(ids));
    }

    @ResponseBody
    @GetMapping("out-bound/{sn}")
    public ResponseBean<Boolean> outBound(@PathVariable String sn){
        Boolean success = outBound(Collections.singletonList(sn));

        return ResponseBean.success(success);
    }

    @ResponseBody
    @PostMapping("out-bound-batch")
    public ResponseBean<Boolean> outBoundMaterialBatch(@RequestBody List<String> snList){
        Boolean success = outBound(snList);

        return ResponseBean.success(success);
    }


    private Boolean outBound(List<String> snList) {
        if(CollectionUtils.isEmpty(snList)){
            throw new BaseException("请输入SN后出库！");
        }

        List<MaterialRecordPO> dataList = materialService.lambdaQuery().in(MaterialRecordPO::getSn, snList).list();
        if(CollectionUtils.isEmpty(dataList)){
            throw new BaseException("未找到需要出库的物料！");
        }

        Set<Integer> statusSet = dataList.stream().map(MaterialRecordPO::getOutBound).collect(Collectors.toSet());
        if(statusSet.contains(OutBoundStatusEnums.OUT_BOUND.getStatus())){
            throw new BaseException("出库失败，存在已出库的物料！");
        }

        dataList.forEach(data -> data.setOutBound(OutBoundStatusEnums.OUT_BOUND.getStatus()));

        return materialService.updateBatchById(dataList);
    }
}
